package com.dh.convert.mapping;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.util.TypeUtils;
import com.dh.convert.constants.Constants;
import com.dh.convert.exception.ConvertInitException;
import com.dh.convert.rule.validator.AbstractValidator;
import com.dh.convert.rule.validator.ValidatorContext;
import com.dh.convert.utils.ClassUtils;
import com.google.common.base.Splitter;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class BeanMappingObject {

	/* 源属性名 */
	private String srcField;
	/* 源属性el */
	private Expression srcFieldExpression;
	/* 原el属性名中包含的List名称 */
	private String srcList;
	/* 目标属性名 */
	private String targetField;
	/*
	 * 属性类型 反序列化、bean copy为源类型 序列化时为目标类型
	 */
	private String type;
	/*
	 * 属性类 对应属性类型
	 */
	private Class<?> typeClass;
	/* 集合映射 Y-是 N-否 */
	private String collectionMapping;
	/* 校验器字符串 */
	private String validate;
	/* 校验器 */
	private List<BeanMappingValidator> validators;
	/* 条件表达式 */
	private String el;
	/* 规则表达式 */
	private String rule;
	/* 默认值 */
	private String defaultValue;
	private Object castdeFaultValue;
	private Expression ruleExpression;
	private Expression expression;
	private Boolean firstEl;

	public String getSrcList() {
		return srcList;
	}

	public Expression getSrcFieldExpression() {
		return srcFieldExpression;
	}

	public String getType() {
		return type;
	}

	public Class<?> getTypeClass() {
		return typeClass;
	}

	public void setType(String type) {
		this.type = type;
	}

	public void setTypeClass(Class<?> typeClass) {
		this.typeClass = typeClass;
	}

	public String getSrcField() {
		return srcField;
	}

	public String getTargetField() {
		return targetField;
	}

	public void setSrcField(String srcField) {
		this.srcField = srcField;
	}

	public void setTargetField(String targetField) {
		this.targetField = targetField;
	}

	public String getDefaultValue() {
		return defaultValue;
	}

	public void _castDefaultValue() {
		if (StringUtils.isNoneBlank(defaultValue)) {
			if (ClassUtils.isColltion(typeClass))
				this.castdeFaultValue = JSON.parseArray(defaultValue);
			else
				this.castdeFaultValue = TypeUtils.castToJavaBean(defaultValue, typeClass);
		}
	}

	public Boolean getFirstEl() {
		return firstEl;
	}

	public void setFirstEl(Boolean firstEl) {
		this.firstEl = firstEl;
	}

	@Override
	public String toString() {
		return "BeanMappingObject [srcField=" + srcField + ", targetField=" + targetField + ", type=" + type
				+ ", collectionMapping=" + collectionMapping + ", validate=" + validate + ", el=" + el + ", rule="
				+ rule + ", defaultValue=" + defaultValue + ", castdeFaultValue=" + castdeFaultValue + "firstEl="
				+ firstEl + "]";
	}

	public String getRule() {
		return rule;
	}

	public void setRule(String rule) {
		this.rule = rule;
	}

	public Object getCastDefaultValue() {
		return castdeFaultValue;
	}

	public String getCollectionMapping() {
		return collectionMapping;
	}

	public void setCollectionMapping(String collectionMapping) {
		this.collectionMapping = collectionMapping;
	}

	public void setDefaultValue(String defaultValue) {
		this.defaultValue = defaultValue;
	}

	public String getValidate() {
		return validate;
	}

	public String getEl() {
		return el;
	}

	public void setValidate(String validate) {
		this.validate = validate;
	}

	public void setEl(String el) {
		this.el = el;
	}

	public void buildValidator() {
		if (StringUtils.isNoneBlank(validate)) {
			List<String> validates = Splitter.on("|").trimResults().splitToList(validate);
			validators = new ArrayList<BeanMappingValidator>();
			for (String s : validates) {
				int index1 = s.indexOf("(");
				int index2 = s.indexOf(")");
				String errorMsg = null;
				String validatorName = s;
				if (index1 != -1 && index2 != -1) {
					errorMsg = s.substring(index1 + 1, index2);
					validatorName = s.substring(0, index1);
				}
				AbstractValidator validator = ValidatorContext.get(validatorName);
				if (validator != null) {
					BeanMappingValidator bv = new BeanMappingValidator();
					bv.setValidator(validator);
					bv.setErrorMsg(errorMsg);
					validators.add(bv);
				}
			}
		}
	}

	public void compile() {
		if (StringUtils.isNoneBlank(el)) {
			this.expression = AviatorEvaluator.compile(el);
		}
		if (StringUtils.isNoneBlank(rule)) {
			this.ruleExpression = AviatorEvaluator.compile(rule);
		}
	}

	public void parseSrcField() {
		if (StringUtils.isNoneBlank(srcField)) {
			StringBuilder buf = new StringBuilder(srcField);
			int startIndex = buf.indexOf(Constants.PLACE_PREFIX);
			boolean isEl = Boolean.FALSE;
			while (startIndex != -1) {
				int endIndex = buf.lastIndexOf(Constants.PLACE_ENDINDEX);
				if (endIndex != -1) {
					if (startIndex != 0 && buf.charAt(startIndex - 1) == Constants.LIST_FLAG) {
						String listToken = buf.substring(startIndex + Constants.PLACE_ENDINDEX.length(), endIndex);
						int flagIndex = listToken.indexOf(Constants.LIST_FLAG);
						if (flagIndex != -1) {
							this.srcList = listToken.substring(0, flagIndex).trim();
						} else {
							this.srcList = listToken.trim();
						}
						buf.setCharAt(startIndex - 1, Constants.REPLACE);
					}
					buf.setCharAt(startIndex, Constants.REPLACE);
					buf.setCharAt(endIndex, Constants.REPLACE);
				}else{
					throw new ConvertInitException("srcField error " + srcField);
				}
				startIndex = buf.indexOf(Constants.PLACE_PREFIX);
				isEl = Boolean.TRUE;
			}
			if (isEl) {
				String el = StringUtils.remove(buf.toString(), Constants.REPLACE)
						.replace(this.srcList + Constants.LIST_FLAG, Constants.CURRENT_LIST_ENTRY);
				this.srcFieldExpression = AviatorEvaluator.compile(el);
			}
		}

	}

	public Expression getRuleExpression() {
		return ruleExpression;
	}

	public Expression getExpression() {
		return expression;
	}

	public List<BeanMappingValidator> getValidators() {
		return validators;
	}
}
